package com.ymwk;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.ymwk.base64.Base64Utils;
import com.ymwk.result.Result;
import com.ymwk.sm2.GMBaseUtil;
import com.ymwk.sm2.SM2CertUtil;
import com.ymwk.sm2.SM2Util;
import com.ymwk.sm4.Sm4Utils;

/**
 * 对字符串的数字信封
 * @author Saxon
 * @Date   2021年7月9日
 */
public class StrEncrypt extends GMBaseUtil{
	
	
	public static final String charset = "utf8";

	/**
	 * @param publicKey 公钥对象
	 * @param orgData  原文
	 * @return Result if(code== 200）success else fail   
	 * encryptFileStr 加密后的字符串
	 * encryptKeyStr  加密后的秘钥字符串
	 * @throws UnsupportedEncodingException 
	 * @throws NoSuchProviderException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static Result strEncrypt(PublicKey publicKey,String orgData) throws UnsupportedEncodingException {
		try {
			//创建对称秘钥对
			byte[] key = Sm4Utils.generateKey();
			//对加密
			byte[] fileEncryptBytes = Sm4Utils.encrypt_ECB_Padding(key, orgData.getBytes(charset));
			//对秘钥对加密
			byte[] encryptKey = SM2Util.encrypt((BCECPublicKey)publicKey, key);
			//将返回值base64加密
			String encryptDataStr = Base64Utils.encode(fileEncryptBytes);
			String encryptKeyStr = Base64Utils.encode(encryptKey);
			return new Result(Result.CODE_SUCCESS,"加密成功", encryptDataStr,encryptKeyStr);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return new Result(Result.CODE_EXCEPTION, "NoSuchAlgorithmException,没有找到该摘要算法");
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
			return new Result(Result.CODE_EXCEPTION, "NoSuchProviderException,没有找到该加密机");
		}catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | InvalidCipherTextException e ) {
			e.printStackTrace();
			return new Result(Result.CODE_EXCEPTION, "加密失败:"+e.getMessage());
		}
	}
	
	/**
	 * 
	 * @param cert  证书对象
	 * @param orgData 原文
	 * @return Result if(code== 200）success else fail   
	 * encryptFileStr 加密后的数据字符串
	 * encryptKeyStr  加密后的秘钥字符串
	 */
	public static Result strEncrypt(X509Certificate cert,String orgData) throws IOException {
		return strEncrypt(SM2CertUtil.getBCECPublicKey(cert),orgData);
	}
	
	/**
	 * @param certStr  证书base64
	 * @param orgData  原文
	 * @return Result if(code== 200）success else fail   
	 * encryptFileStr 加密后的数据字符串
	 * encryptKeyStr  加密后的秘钥字符串
	 * @throws IOException 
	 */
	public static Result fileEncrypt(String certStr,String orgData) throws CertificateException, NoSuchProviderException, IOException {
		   ByteArrayInputStream bais = new ByteArrayInputStream(Base64Utils.decode(certStr));
		   CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
		return strEncrypt((X509Certificate) cf.generateCertificate(bais),orgData);
	}
	
	public static void main(String[] args) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException {
		Security.addProvider(new BouncyCastleProvider());
		String publicKeyStr = "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v////////////////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEjAgEBA0IABMWwe7cKGGDCHWVCCmI195Ump1xqhZcXn7oYa23gNPUYs8vAxmC/nf7t+8Kq7Iq2KR5zlafOR5+Igs/BX4AkUkQ=";
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64Utils.decode(publicKeyStr));
		 KeyFactory keyFactory = KeyFactory.getInstance("EC");
	    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
	    Result strEncrypt = strEncrypt(publicKey,"吴赏群yyds666");
		System.out.println(strEncrypt);
		
	}
}
